<?php
/**
 * @see Zend_Form_Element_Multi
 */
require_once "Zend/Form/Element/Multi.php";

/**
 * Элемент формы, реализующий выбор элементов для модуля форм
 * 
 * @category Phorm
 * @package JQuery_Form_Element
 * @name /Phorm/JQuery/Form/Element/FormsElements.php
 * @copyright phorm.ru
 * @since 20.02.2011
 * @author vladimir@kachalov.net
 */

class Phorm_JQuery_Form_Element_FormsElements extends Zend_Form_Element_Multi {
	
	/**
	 * Имя метода - помощника вида
	 * @var string
	 */
	public $helper = 'formsElements';
	
	/**
	 * Массив используемых элементов форм
	 * @var array
	 */
	public $elements = array();
	
	/**
	 * Массив конфигураций мини-форм
	 * @var array
	 */
	public $configs = array();
	
	/**
	 * Массив отрендеренных мини-форм
	 * @var array
	 */
	public $renders = array();
	
	/**
	 * Массив объектов Zend_Form мини-форм
	 * @var array
	 */
	public $forms = array();
	
	/**
	 * Массив объектов Zend_Form каждого из пришедших элементов
	 * @var array
	 */
	public $vforms = array();
	
	/**
	 * Объект переводчика
	 * @var object
	 */
	protected $translate;
	
	/**
	 * Определяем массив опций и дергаем родительский конструктор
	 *
	 * @param mixed $spec
	 * @param array $options
	 */
	
	public function __construct($spec, $options = null) {
		
		$this->translate = Zend_Controller_Front::getInstance()->getParam('bootstrap')->getResource('Translate');
		$this->elements = $this->getElements();
		$this->configs = $this->getConfigs();
		$this->forms = $this->getForms();
		$this->renders = $this->getRenders();

		/**
		 * Формируем выпадающий список с типами элементов
		 */
		
		$options['multioptions'] = array(null => $this->translate->_('---Выберите---'));
		
		foreach ($this->configs as $fieldtype=>$form) {
			$options['multioptions'][$fieldtype] = $form['label'];
		}
		
		/**
		 * Инициализируем родительский конструктор
		 */
		
		parent::__construct($spec, $options);
		
	}

	
	/**
	 * Возвращает список элементов, используемых в мини-формах
	 *
	 * @return array
	 * @todo перенести в xml-конфиги и мб сделать управление по типу виджетов
	 */
	
	public function getElements() {
		
		$elements = array(
		
			'fieldtype' => array(
				'type' => 'Hidden',
				'options' => array('decorators' => array('ViewHelper'), 'filters' => array('StringTrim')),
			),
			
			'fieldid' => array(
				'type' => 'Hidden',
				'options' => array('decorators' => array('ViewHelper'), 'filters' => array('Int')),
			),
		
			'fieldname' => array(
				'type' => 'Text',
				'options' => array('label' => 'Название поля', 'class' => 'wp100 ui-widget-content', 'required' => true, 'filters' => array('StringTrim')),
			),
			
			'fieldtxt' => array(
				'type' => 'Textarea',
				'options' => array('label' => 'Описание поля', 'class' => 'wp100 h80 ui-widget-content', 'filters' => array('StringTrim')),
			),
			
			'optionsdata' => array(
				'type' => 'Textarea',
				'options' => array('label' => 'Элементы списка (по одному на строчку)', 'class' => 'wp100 h80 ui-widget-content', 'filters' => array('StringTrim')),
			),
			
			'isrequired' => array(
				'type' => 'Select',
				'options' => array('label' => 'Обязательное', 
								   'multioptions' => array(
								   						'yes' => 'Да',
								   						'no'  => 'Нет'),
								   'class' => 'ui-widget-content'),
			),
			
			'htmlallowed' => array(
				'type' => 'Select',
				'options' => array('label' => 'Разрешены ли HTML-теги', 
								   'multioptions' => array(
								   						'yes' => 'Да',
								   						'no'  => 'Нет'),
								   'class' => 'ui-widget-content'),
			),
			
			'fieldvalidators' => array(
				'type' => 'Select',
				'options' => array('label' => $this->translate->_('Параметры валидации'), 
								   'multioptions' => array(
								   						null => 'Нет',
								   						'Email' => 'Email-адрес',
								   						'Date' => 'Дата/время',
								   						'Int' => 'Только цифры',
								   						'Hostname' => 'Адрес сайта'),
								   'class' => 'ui-widget-content'),
			),
			
			'filestypes' => array(
				'type' => 'Select',
				'options' => array('label' => $this->translate->_('Типы файлов'), 
								   'multioptions' => array(
								   						'Images' => 'Изображения',
								   						'Documents' => 'Офисные документы',
								   						'Archives' => 'Файловые архивы'),
								   'class' => 'ui-widget-content'),
			),
			
		);
		
		return $elements;
		
	}
	
	
	/**
	 * Возвращает массив конфигураций мини-форм по типам 
	 *
	 * @return array
	 * @todo добавить тип поля мультичекбокс
	 */
	
	public function getConfigs() {
		
		$elements = $this->elements;
		
		$forms = array(
		
			'Text' => array(
				'label' => 'Однострочное текстовое поле',
				'elements' => array(
					'fieldtype' => array_merge_recursive($elements['fieldtype'],array('options' => array('value' => 'Text'))),
					'fieldid' => $elements['fieldid'],
					'fieldname' => $elements['fieldname'],
					'fieldtxt' => $elements['fieldtxt'],
					'isrequired' => $elements['isrequired'],
					'htmlallowed' => $elements['htmlallowed'],
					'fieldvalidators' => $elements['fieldvalidators'],
				),
			),
			
			'Textarea' => array(
				'label' => 'Многострочное текстовое поле',
				'elements' => array(
					'fieldtype' => array_merge_recursive($elements['fieldtype'],array('options' => array('value' => 'Textarea'))),
					'fieldid' => $elements['fieldid'],
					'fieldname' => $elements['fieldname'],
					'fieldtxt' => $elements['fieldtxt'],
					'isrequired' => $elements['isrequired'],
					'htmlallowed' => $elements['htmlallowed'],
				),
			),
			
			'Html' => array(
				'label' => 'HTML-текст',
				'elements' => array(
					'fieldtype' => array_merge_recursive($elements['fieldtype'],array('options' => array('value' => 'Html'))),
					'fieldid' => $elements['fieldid'],
					'fieldname' => $elements['fieldname'],
					'fieldtxt' => $elements['fieldtxt'],
					'isrequired' => $elements['isrequired']
				),
			),
			
			'Bbcode' => array(
				'label' => 'BBcode-текст',
				'elements' => array(
					'fieldtype' => array_merge_recursive($elements['fieldtype'],array('options' => array('value' => 'Bbcode'))),
					'fieldid' => $elements['fieldid'],
					'fieldname' => $elements['fieldname'],
					'fieldtxt' => $elements['fieldtxt'],
					'isrequired' => $elements['isrequired']
				),
			),
			
			'Checkbox' => array(
				'label' => 'Переключатель (чекбокс)',
				'elements' => array(
					'fieldtype' => array_merge_recursive($elements['fieldtype'],array('options' => array('value' => 'Checkbox'))),
					'fieldid' => $elements['fieldid'],
					'fieldname' => $elements['fieldname'],
					'fieldtxt' => $elements['fieldtxt'],
					'isrequired' => $elements['isrequired'],
				),
			),
			
			'Radio' => array(
				'label' => 'Радиоточка',
				'elements' => array(
					'fieldtype' => array_merge_recursive($elements['fieldtype'],array('options' => array('value' => 'Radio'))),
					'fieldid' => $elements['fieldid'],
					'fieldname' => $elements['fieldname'],
					'fieldtxt' => $elements['fieldtxt'],
					'isrequired' => $elements['isrequired'],
				),
			),
			
			'Select' => array(
				'label' => 'Выпадающий список',
				'elements' => array(
					'fieldtype' => array_merge_recursive($elements['fieldtype'],array('options' => array('value' => 'Select'))),
					'fieldid' => $elements['fieldid'],
					'fieldname' => $elements['fieldname'],
					'fieldtxt' => $elements['fieldtxt'],
					'isrequired' => $elements['isrequired'],
					'optionsdata' => $elements['optionsdata'],
				),
			),
			
			'Multiselect' => array(
				'label' => 'Список с множественным выбором',
				'elements' => array(
					'fieldtype' => array_merge_recursive($elements['fieldtype'],array('options' => array('value' => 'Multiselect'))),
					'fieldid' => $elements['fieldid'],
					'fieldname' => $elements['fieldname'],
					'fieldtxt' => $elements['fieldtxt'],
					'isrequired' => $elements['isrequired'],
					'optionsdata' => $elements['optionsdata'],
				),
			),
			
			'File' => array(
				'label' => 'Выбор файла для загрузки',
				'elements' => array(
					'fieldtype' => array_merge_recursive($elements['fieldtype'],array('options' => array('value' => 'File'))),
					'fieldid' => $elements['fieldid'],
					'fieldname' => $elements['fieldname'],
					'fieldtxt' => $elements['fieldtxt'],
					'isrequired' => $elements['isrequired'],
					'filestypes' => $elements['filestypes'],
				),
			),
			
			'Captcha' => array(
				'label' => 'CAPTCHA',
				'elements' => array(
					'fieldtype' => array_merge_recursive($elements['fieldtype'],array('options' => array('value' => 'Captcha'))),
					'fieldid' => $elements['fieldid'],
					'fieldname' => $elements['fieldname'],
					'fieldtxt' => $elements['fieldtxt'],
				),
			),
			
			'Refferer' => array(
				'label' => 'Скрытое поле Refferer',
				'elements' => array(
					'fieldtype' => array_merge_recursive($elements['fieldtype'],array('options' => array('value' => 'Refferer'))),
					'fieldid' => $elements['fieldid'],
					'fieldname' => $elements['fieldname'],
					'isrequired' => $elements['isrequired'],
				),
			),
			
		);
		
		return $forms;
		
	}
	
	
	/**
	 * Возвращает массив объектов Zend_Form мини-форм по типам 
	 *
	 * @return array
	 */
	
	public function getForms() {
		
		$forms = array();
		
		foreach ($this->configs as $fieldtype => $template) {
			
			$form = new Zend_Form($template);
		    $form -> setElementsBelongTo('fields[]');
		    $form -> addDisplayGroup(
		    			array_keys($template['elements']),
		    			'main',
		    			array('legend' => $template['label'],
		    				  'class' => 'ui-widget-content'));
		    $form -> removeDecorator('Form');
		    $form -> removeDecorator('DtDdWrapper');
		    $form -> setTranslator($this->translate);
		    
		    $forms[$fieldtype] = $form;
			
		}
		
		return $forms;
		
	}
	
	
	/**
	 * Возвращает массив отрендеренных мини-форм по типам 
	 *
	 * @return array
	 */
	
	public function getRenders() {
		
		$renders = array();
		
		foreach ($this->forms as $fieldtype => $form) {
		    
		    $renders[$fieldtype] = $form->render();
			
		}
		
		return $renders;
		
	}
	
	
	/**
	 * Валидация элемента
	 *
	 * @param mixed $value
	 * @return boolean
	 */
	
	public function isValid($value) {
		
		$this->setValue($value);
        $value = $this->getValue();
		
		if(!is_array($value)) {
			$this->_messages = array($this->translate->_('Не задано ни одного поля формы'));
			return false;
		}
		
		$result = true;
		
		$this->_messages = array();
        $this->_errors   = array();
        
        $i = 1;
		
		foreach ($value as $key=>$mini_form) {
			
			if(isset($mini_form['fieldtype']) && isset($this->forms[$mini_form['fieldtype']])) {
				
				$form = $this->vforms[$key];
				
				if(!$form->isValid($mini_form)) {	
					$this->_messages[] = $this->translate->_('Ошибка в поле №') . $i . ' (' . $this->configs[$mini_form['fieldtype']]['label'] . ')';
					$result = false;
				}
				
			} else {
				
				$this->_messages[] = isset($mini_form['fieldtype']) ? 
									 $this->translate->_('Невозможно проверить тип поля №') . $i . ' (' . $mini_form['fieldtype'] . ')' : 
									 $this->translate->_('Невозможно определить тип поля №') . $i;
				$result = false;
				
			}
			
			$i++;
			
		}
		
		return $result;
		
	}
	
	
	/**
     * Set element value
     *
     * @param  array $value
     * @return Zend_Form_Element
     */
	
    public function setValue($value) {
    	
    	if(!is_array($value)) return $this;
    	
        $this->_value = $value;
        
        foreach ($value as $mini_form) {	
	        $form = clone $this->forms[$mini_form['fieldtype']];
	        $this->vforms[] = $form->setDefaults($mini_form);
		}
        
        return $this;
        
    }
	
}